// import Message from "./Message";
let message = {
  error (params) {
    console.error(params);
  },
  success (params) {
    console.log(
      `%c success: %c ${params} `,
      `color:#fff;
      background-color:#42c02e;
        border-top-left-radius: 1em;
        border-bottom-left-radius: 1em;
    `,
      "color:#fff;background-color:#1475b2;border-top-right-radius: 1em;border-bottom-right-radius: 1em;"
    );
  },
};

class Shios {
  constructor({ baseUrl }) {
    this.baseUrl = baseUrl;
    this.message = message;
    this.headers = JSON.parse(window.sessionStorage.getItem("headers"));
    this.caches = {};
    this.instance = null;
    this.assert = null;
    this.verifyState = null;
    this.UrlToLowerCase = false;
    this.IsShowLog = false;
  }
  joinUrl (action, id, isGet) {
    if (!isGet) {
      let cacheName = (/(?<=\/api\/)\w+/).exec(action)[0];
      if (this.caches[cacheName]) {
        delete this.caches[cacheName];
      } else {
        let keys = Object.keys(this.caches);
        if (keys.length > 0) {
          let name = keys[keys.length - 1];
          if(this.IsShowLog)
            console.log(name);
          // debugger;
          delete this.caches[name];
        }
      }
    }
    let url;
    if ((/^http/).test(action)) {
      url = action;
    } else {
      url = `${this.baseUrl}${action}`;
    }
    if (typeof id === "object") {
      let args = action.includes("?") ? "&" : "?";
      for (const key in id) {
        if (Object.hasOwnProperty.call(id, key)) {
          if (id[key] === 0 || id[key]) {
            args += `${key}=${id[key]}&`;
            // args += `${key}=${window.encodeURIComponent(id[key])}&`;
          }
        }
      }
      args = args.substring(0, args.length - 1);
      url += args;
    } else {
      url += `${id ? "/" + id : ""}`;
    }
    return url;
  }
  async myFetch (action, id, init) {
    let url = this.joinUrl(action, id);
    if(this.UrlToLowerCase)
      url = url.toLocaleLowerCase();
    if(this.IsShowLog)
      console.log(url);
    let cacheName = (/(?<=api\/)\w+/).exec(action)[0];
    if (init.method === "GET") {
      if (this.caches[cacheName] && url in this.caches[cacheName]) {
        return this.caches[cacheName][url];
      }
    } else {
      if (this.caches[cacheName]) { // 删除缓存
        delete this.caches[cacheName];
      } else {
        let keys = Object.keys(this.caches);
        if (keys.length > 0) { // 删除缓存最后入库的那个
          let name = keys[keys.length - 1];
          // debugger;
          delete this.caches[name];
        }
      }
    }
    const headers =
      this.headers || JSON.parse(window.sessionStorage.getItem("headers"));

    init.headers = {
      ...init.headers,
      ...headers,
    };

    try {
      let response = await fetch(url, init);
      response.header = headers;
      switch (response.status) {
        case 401:
          window.sessionStorage.clear();
          this.message.error("登录超时，请重新登录");
          break;
        case 403:
          this.message.error("权限不足，请确认当前用户是否有足够访问权限");
          break;
        case 204:
          return response;
        default:
          response.data = await response.json();
          break;
      }

      if (!response.ok) {
        throw response;
      }
      if (this.verifyState) {
        this.verifyState(response);
      }
      if (init.method === "GET") {
        if (!(/Common|check/i).test(cacheName)) {
          this.caches[cacheName] = {
            ...this.caches[cacheName],
            [url]: response,
          };
        }
      }
      return response;

    } catch (error) {
      if (!error.status) {
        this.message.error("请求失败,服务器无响应");
      }
      if (this.verifyState) {
        this.verifyState(error);
      }
      throw error;
    }
  }
  async get (action = "", id) {
    // let url = this.joinUrl(action, id, true);

    // let cacheName = /(?<=api\/)\w+/.exec(action)[0];
    // if (this.caches[cacheName] && url in this.caches[cacheName]) {
    //   return this.caches[cacheName][url];
    // }

    let response = await this.myFetch(action, id, {
      method: "GET",
      headers: {
        Accept: "application/json",
      },
    });
    // if (!/Common|check/i.test(cacheName)) {
    //   this.caches[cacheName] = { ...this.caches[cacheName], [url]: response };
    // }
    return response;
  }
  async post (action = "", data, id) {
    // let url = this.joinUrl(action, id);
    const response = await this.myFetch(action, id, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    });
    // if (typeof response.data.Data !== "string" && response.data.Code === 200) {
    //   this.message.success(response.data.Message);
    // }
    if (this.assert) {
      this.assert(response);
    }
    if (this.IsShowLog) {

      console.log(response);
    }
    return response;
  }
  async upload (action = "", formData, id) {
    // let url = this.joinUrl(action, id);
    return await this.myFetch(action, id, {
      method: "POST",
      body: formData,
    });
  }
  async put (action = "", id) {
    return await this.myFetch(action, id, {
      method: "PUT",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(id),
    });
  }
  async patch (action = "", item, id) {
    if (!id) {
      throw "id 为空";
    }

    if (!item) {
      throw `item is ${item}`;
    }

    let response = await this.myFetch(action, id, {
      method: "PATCH",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify(item),
    });

    if (response.ok) {
      return response;
    }
    throw response;
  }
  async delete (action = "", id) {
    // let url = this.joinUrl(action, id);

    let response = await this.myFetch(action, id, {
      method: "DELETE",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    });
    if (response.ok) {
      this.message.success(response.data.Message);
      return response;
    }
    throw response;
  }
  static create ({ baseUrl }) {
    if (!this.instance) {
      this.instance = new Shios({ baseUrl });
    }
    return this.instance;
  }
}

export default Shios;
